package datamanager;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

import repast.simphony.space.grid.Grid;
import repast.simphony.space.grid.GridPoint;
import repast.simphony.valueLayer.GridValueLayer;
import repast.simphony.valueLayer.ValueLayer;
import defectsim.DefectAgent;
import defectsim.Dislocation;
import defectsim.DislocationSource;
import defectsim.EdgeDislocation;
import defectsim.SimEnvironment;
import defectsim.Util;
import defectsim.DefectFactory.DefectType;

public class DataWriter {

	SimEnvironment env = SimEnvironment.getInstance();

	@SuppressWarnings("unchecked")
	public void saveExistence(String fileName, DefectType type) throws ClassNotFoundException{
		int gridSize = env.getGridSize();
		int[][] existence = new int[gridSize][gridSize];
		BufferedWriter out = null;

		Grid grid = (Grid) env.getContext().getProjection(env.getGridName());
		Iterable<DefectAgent> allDefects = grid.getObjects();

		String className = "";
		switch (type){
		case EdgeDislocation:
			className = EdgeDislocation.class.getName();
			break;
		case DislocationSource:
			className = DislocationSource.class.getName();
			break;
		}
		for (Object defect : allDefects) {
			if (Class.forName(className).isInstance(defect)){
				EdgeDislocation d = (EdgeDislocation)defect;
				GridPoint location = grid.getLocation(d);
				//				if (!d.isDipole())
				existence[location.getX()][location.getY()] = 1;
			}
		}
		try {
			out = new BufferedWriter(new FileWriter(fileName));
			for (int i = 0; i < gridSize; i++) {
				String s = "";
				for (int j = 0; j < gridSize; j++){
					s = s + Integer.toString(existence[i][j]) + " ";
				}
				s = s + "\n";
				out.write(s);
			}
			out.close();
		}
		catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	@SuppressWarnings("unchecked")
	public void saveStress(String filename) throws IOException{
		double minValue = 0.0;
		double maxValue = 0.0;
		double spaceToGridScale = env.getSpaceLength() / env.getGridSize();

		GridValueLayer sf = (GridValueLayer)env.getContext().getValueLayer(env.getElasticStressFieldName());

		Grid grid = (Grid) env.getContext().getProjection(env.getGridName());
		for (int i = 0; i < grid.getDimensions().getWidth(); i++)
			for (int j = 0; j < grid.getDimensions().getHeight(); j++){
				Iterable<Dislocation> neighbors = grid.getObjects();
				double f0 = 0;
				for (Object o : neighbors) {
					if (o instanceof Dislocation){
						Dislocation dis = (Dislocation)o;
						GridPoint gp = grid.getLocation(dis);
						double x = (i - gp.getX()) * spaceToGridScale;
						double y = (j - gp.getY()) * spaceToGridScale;
						double l = Math.sqrt(x * x + y * y);
						double angle = StrictMath.atan2(x, y);
						while(0 > angle) {
							angle += 2.0 * Math.PI;
						}
						if (l != 0.0){
//							double f = Util.calculateGlideStressInCylindiricalCoordinates(l, angle, 
//									dis.getUnitBurgersVector(), env.getCurrentMaterial());
							double f = 0;
							f0 = f0 + f;
						}
					}
				}
				sf.set(f0, i, j);
				if (f0 > maxValue)
					maxValue = f0;
				if (f0 < minValue)
					minValue = f0;
				//				System.out.println(i);
			}
//		sf.set(minValue, 0, 0);
//		sf.set(maxValue, 0, 1);
		SaveValueLayer(sf, filename);
	}

	public void SaveValueLayer(ValueLayer vl, String fname){
		BufferedWriter out = null;
		double spaceToGridScale = env.getSpaceLength() / env.getGridSize();

		try {
			out = new BufferedWriter(new FileWriter(fname));
			for (int i = 0; i < vl.getDimensions().getWidth(); i++) {
				String s = "";
				for (int j = 0; j < vl.getDimensions().getHeight(); j++){
					s = Double.toString(i * spaceToGridScale) + " " + Double.toString(j * spaceToGridScale) + " " + Double.toString(vl.get(i, j)) + "\n";
					out.write(s);
				}
				out.write("\n");
			}
			out.close();
		}
		catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}
	public DataWriter(){

	}
}
